import ThreejsNanningMap from './ThreejsNanningMap'
const THREE = window.THREE

class ThreejsOutlineMap extends ThreejsNanningMap {
  constructor(set) {
    super(set)
    const { outlineData } = set
    this.outlineData = outlineData
    this.uniforms2 = {
      u_time: { value: 0.0 }
    }
    this.outlineInit()
    this.outlineAnimate()
  }

  outlineInit() {
    this.outLineMap()
  }

  // 流光南宁
  outLineMap() {
    this.outlineData.features.forEach((elem) => {
      const province = new THREE.Object3D()
      const coordinates = elem.geometry.coordinates
      coordinates.forEach((multiPolygon) => {
        multiPolygon.forEach((polygon) => {
          if (polygon.length > 200) {
            const v3ps = []
            for (let i = 0; i < polygon.length; i++) {
              const [x, y, z] = this.lnglatToMector(polygon[i])
              v3ps.push(new THREE.Vector3(x, y, z + 2.4))
            }
            const curve = new THREE.CatmullRomCurve3(v3ps, false, 'catmullrom', 0.05)
            const color = new THREE.Color('#10bff4')
            const flyLine = this.initFlyLine(curve, {
              speed: 0.2,
              color: color,
              number: 3, // 同时跑动的流光数量
              length: 0.1, // 流光线条长度
              size: 4 // 粗细
            }, 5000)
            province.add(flyLine)
          }
        })
      })
      this.scene.add(province)
    })
  }

  initFlyLine(curve, matSetting, pointsNumber) {
    const points = curve.getPoints(pointsNumber)
    const geometry = new THREE.BufferGeometry().setFromPoints(points)
    const length = points.length
    const percents = new Float32Array(length)
    for (let i = 0; i < points.length; i += 1) {
      percents[i] = (i / length)
    }
    geometry.setAttribute('percent', new THREE.BufferAttribute(percents, 1))
    const lineMaterial = this.initLineMaterial(matSetting)
    const flyLine = new THREE.Points(geometry, lineMaterial)
    return flyLine
  }

  initLineMaterial(setting) {
    const number = setting ? (Number(setting.number) || 1.0) : 1.0
    const speed = setting ? (Number(setting.speed) || 1.0) : 1.0
    const length = setting ? (Number(setting.length) || 0.5) : 0.5
    const size = setting ? (Number(setting.size) || 3.0) : 3.0
    const color = setting ? setting.color || new THREE.Vector3(0, 1, 1) : new THREE.Vector3(0, 1, 1)
    const singleUniforms = {
      u_time: this.uniforms2.u_time,
      number: { type: 'f', value: number },
      speed: { type: 'f', value: speed },
      length: { type: 'f', value: length },
      size: { type: 'f', value: size },
      color: { type: 'v3', value: color }
    }
    const lineMaterial = new THREE.ShaderMaterial({
      uniforms: singleUniforms,
      vertexShader: ThreejsOutlineMap.gradient.vs,
      fragmentShader: ThreejsOutlineMap.gradient.fs,
      transparent: true
      // blending:THREE.AdditiveBlending,
    })
    return lineMaterial
  }

  outlineAnimate() {
    requestAnimationFrame(this.outlineAnimate.bind(this))
    this.uniforms2.u_time.value += 0.007
  }

  static gradient = {
    vs: `
      varying vec2 vUv;
      attribute float percent;
      uniform float u_time;
      uniform float number;
      uniform float speed;
      uniform float length;
      varying float opacity;
      uniform float size;
      void main()
      {
          vUv = uv;
          vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
          float l = clamp(1.0-length,0.0,1.0);
          gl_PointSize = clamp(fract(percent*number + l - u_time*number*speed)-l ,0.0,1.) * size * (1./length);
          opacity = gl_PointSize/size;
          gl_Position = projectionMatrix * mvPosition;
      }
    `,
    fs: `
      #ifdef GL_ES
      precision mediump float;
      #endif
      varying float opacity;
      uniform vec3 color;
      void main(){
          if(opacity <=0.2){
              discard;
          }
          gl_FragColor = vec4(color,1.0);
      }
    `
  }
}

export default ThreejsOutlineMap
